import 'package:flutter/cupertino.dart' hide RefreshCallback;
import 'package:flutter/material.dart';

import '../base_stateless_widget.dart';

/// BaseIndicator
/// use CustomScrollView + CupertinoSliverRefreshControl by cupertino
/// *** use cupertino = { forceUseMaterial: true } force use RefreshIndicator on cuperitno.
/// use RefreshIndicator by material
/// *** use material = { forceUseCupertino: true } force use CupertinoSliverRefreshControl on material.
class BaseRefresh extends BaseStatelessWidget {
  const BaseRefresh({
    Key? baseKey,
    this.key,
    this.refreshTriggerPullDistance = _defaultRefreshTriggerPullDistance,
    this.refreshIndicatorExtent = _defaultRefreshIndicatorExtent,
    this.builder,
    required this.onRefresh,
    required this.child,
    this.displacement = 40.0,
    this.color,
    this.backgroundColor,
    this.notificationPredicate = defaultScrollNotificationPredicate,
    this.semanticsLabel,
    this.semanticsValue,
    Map<String, dynamic>? cupertino,
    Map<String, dynamic>? material,
  }) : super(
      key: baseKey,
      cupertino: cupertino ?? const <String, dynamic>{},
      material: material ?? const <String, dynamic>{}
  );

  /// *** general properties start ***

  /// [CupertinoSliverRefreshControl.key]
  /// or
  /// [RefreshIndicator.key]
  @override
  final Key? key;

  /// [CupertinoSliverRefreshControl.onRefresh]
  /// or
  /// [RefreshIndicator.onRefresh]
  final RefreshCallback onRefresh;

  /// It's SliverList on Cupertino，ListView or CustomScrollView on Material
  /// All three can be converted automatically.
  ///
  /// [CupertinoSliverRefreshControl.child]
  /// or
  /// [RefreshIndicator.child]
  final Widget child;

  /// *** general properties end ***

  /// *** cupertino properties start ***

  /// [CupertinoSliverRefreshControl.refreshTriggerPullDistance]
  final double refreshTriggerPullDistance;

  /// [CupertinoSliverRefreshControl.refreshIndicatorExtent]
  final double refreshIndicatorExtent;

  /// [CupertinoSliverRefreshControl.builder]
  final RefreshControlIndicatorBuilder? builder;

  /// *** cupetino properties end ***

  /// *** material properties start ***

  /// [RefreshIndicator.displacement]
  final double displacement;

  /// [RefreshIndicator.color]
  final Color? color;

  /// [RefreshIndicator.backgroundColor]
  final Color? backgroundColor;

  /// [RefreshIndicator.notificationPredicate]
  final ScrollNotificationPredicate notificationPredicate;

  /// [RefreshIndicator.semanticsLabel]
  final String? semanticsLabel;

  /// [RefreshIndicator.semanticsValue]
  final String? semanticsValue;

  /// *** material properties end ***

  /// [CupertinoSliverRefreshControl]'s _defaultRefreshTriggerPullDistance
  static const double _defaultRefreshTriggerPullDistance = 100.0;

  /// [CupertinoSliverRefreshControl]'s _defaultRefreshIndicatorExtent
  static const double _defaultRefreshIndicatorExtent = 60.0;

  @override
  Widget buildByCupertino(BuildContext context) {
    Widget _child = child;

    // 类型检查和转换
    if (child is ListView) {
      // ListView => SliverList
      final ListView listView = child as ListView;
      _child = SliverList(
        delegate: listView.childrenDelegate,
      );
    } else if (child is CustomScrollView) {
      // CustomScrollView => 直接使用其 slivers
      final CustomScrollView customScrollView = child as CustomScrollView;
      _child = SliverList(
        delegate: SliverChildListDelegate(
          customScrollView.slivers,
        ),
      );
    } else if (!_isSliver(child)) {
      // 如果不是 Sliver，包装为 SliverToBoxAdapter
      _child = SliverToBoxAdapter(
        child: child,
      );
    }

    return CustomScrollView(
      key: valueFromCupertino('key', key),
      slivers: <Widget>[
        CupertinoSliverRefreshControl(
          refreshTriggerPullDistance: refreshTriggerPullDistance,
          refreshIndicatorExtent: refreshIndicatorExtent,
          builder: builder,
          onRefresh: valueFromCupertino('onRefresh', onRefresh),
        ),
        _child as Widget, // 确保类型正确
      ],
    );
  }

  @override
  Widget buildByMaterial(BuildContext context) {
    Widget _child = child;

    // 类型检查和转换
    if (child is SliverList) {
      // SliverList => ListView
      final SliverList sliverList = child as SliverList;
      _child = ListView.custom(
        childrenDelegate: sliverList.delegate,
      );
    } else if (child is CustomScrollView) {
      // CustomScrollView => 提取第一个 SliverList 或使用 ListView
      final CustomScrollView customScrollView = child as CustomScrollView;
      // 这里需要更复杂的逻辑来处理多个 slivers
      // 简化处理：如果只有一个 SliverList，提取它
      if (customScrollView.slivers.length == 1 && customScrollView.slivers.first is SliverList) {
        final SliverList sliverList = customScrollView.slivers.first as SliverList;
        _child = ListView.custom(
          childrenDelegate: sliverList.delegate,
        );
      }
    }

    return RefreshIndicator(
      key: valueFromMaterial('key', key),
      child: _child,
      displacement: displacement,
      color: color,
      backgroundColor: backgroundColor,
      notificationPredicate: notificationPredicate,
      semanticsLabel: semanticsLabel,
      semanticsValue: semanticsValue,
      onRefresh: valueFromMaterial('onRefresh', onRefresh),
    );
  }

  // 检查是否为 Sliver 类型
  bool _isSliver(Widget widget) {
    return widget is SliverList ||
        widget is SliverGrid ||
        widget is SliverToBoxAdapter ||
        widget is SliverFillRemaining ||
        widget is SliverFillViewport ||
        widget is SliverFixedExtentList ||
        widget is SliverPadding ||
        widget is SliverAppBar;
  }
}